package JAVA300.第十章IO;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

/**
 * 随机流学习--面向对象封装
 * 文件分割 读取存储
 *
 * 添加私有成员变量
 * 利用构造器和init函数进行变量初始化
 * Compute函数用于进行计算相关变量
 * read3用于分割
 * 除了需要被对象调用的那个函数以外 尽量都换成private

 */

public class IO_Study16_RandomAccessFile_OOP {

    //源头
    private File srcFile ;
    //目的地文件夹
    private String desDir;
    //分割后所有文件容器
    private List<String> desPath;
    //块大小
    private int blockSize;
    //块数
    private int mount;

    public IO_Study16_RandomAccessFile_OOP(String srcFilePath, String desDirPath, int blockSize) {
        //构造函数参数选不可被计算的，其他就写一个init函数
        this.srcFile = new File(srcFilePath);
        this.desDir = desDirPath;
        this.blockSize = blockSize;
        this.desPath = new ArrayList<String>();

        init();
    }
    //初始化
    public void init(){

        long length = this.srcFile.length();
        //块数
        this.mount = (int) Math.ceil(length*1.0/this.blockSize);//*1.0是转double
        //存储的path
        for (int i=0;i<this.mount;i++){
            desPath.add(this.desDir + "/"+ i + "-"+this.srcFile.getName());
        }
    }

    /**
     * 分割核心函数
     * 1.计算每一块起始位置
     * 2.分割
     * @param
     */
    public void Compute(){

        long length = this.srcFile.length();

        int beginPos =0;
        int actualSize =0;
        for (int i=0;i<this.mount;i++){
            beginPos = i*this.blockSize;
            //实际大小考虑最后一块情况
            if(i == mount-1){
                actualSize = (int)length ;

            }else {
                actualSize = blockSize;
                length -= actualSize;//已经用过了

            }
            System.out.println(i+"-->"+beginPos+"-->"+actualSize);
            //read2(i,beginPos,actualSize);
            read3(i,beginPos,actualSize);
        }


    }



    //在2的基础上进行分块文件的输出
    private  void read3(int i,int beginPos,int actualSize){
        System.out.println(i+"-->"+beginPos+"-->"+actualSize);
        RandomAccessFile raf = null;
        RandomAccessFile rafOut = null;
        try {

            raf = new RandomAccessFile(this.srcFile,"r");
            rafOut = new RandomAccessFile(this.desPath.get(i),"rw");
            raf.seek(beginPos);

            int len =-1;
            byte[] flush = new byte[1024];
            // int actualSize = 9;//每次读了一个汉字，读了三次
            while ((len = raf.read(flush)) != -1){
                if (actualSize > len){
                   // System.out.println(new String(flush,0,len));
                    rafOut.write(flush,0,len);
                    actualSize -= len;
                }else {
                //    System.out.println(new String(flush,0,len));
                    rafOut.write(flush,0,len);

                    break;

                }
            }
            rafOut.close();
            raf.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
        }


    }

    //合并文件1--多输入流单输出流
    public  void merge(String dest){

        try {

            //1个输出流
            OutputStream ops = new BufferedOutputStream(new FileOutputStream(dest));

            //多个输入
            for (int i=0;i<desPath.size();i++){
                InputStream is = new BufferedInputStream(new FileInputStream(desPath.get(i)));

                int len = -1;
                byte[] flush = new byte[1024];
                while ((len = is.read(flush)) != -1){
                    ops.write(flush,0,len);
                }

                ops.flush();
                is.close();
            }

            ops.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    ////合并文件1--借助合并流
    public  void merge1(String dest){

        try {

            //1个输出流
            OutputStream ops = new BufferedOutputStream(new FileOutputStream(dest));
            Vector<InputStream> vi = new Vector<InputStream>();
            SequenceInputStream sis = null;

            //多个输入
            for (int i=0;i<desPath.size();i++){
                vi.add(new BufferedInputStream(new FileInputStream(desPath.get(i)))) ;

            }
            sis = new SequenceInputStream(vi.elements());

            int len = -1;
            byte[] flush = new byte[1024];
            while ((len = sis.read(flush)) != -1){
                ops.write(flush,0,len);
            }

            ops.flush();
            sis.close();
            ops.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        IO_Study16_RandomAccessFile_OOP rafOOP = new IO_Study16_RandomAccessFile_OOP("D:/Java300_Exp/src/JAVA300/第十章IO/IO_Study16_RandomAccessFile_OOP.java",
                "unit10_16out",1024);
        rafOOP.Compute();
        rafOOP.merge1("IO_16MergeOut.java");
    }
}
